﻿using CPPEI.Coolzon.Common;
using CPPEI.Coolzon.UI.XProperty;
using CPPEI.Coolzon.UI.XProperty.Converters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace CPPEI.Coolzon.UI
{
    public static class XPropertyUtility
    {
        /// <summary>
        /// 获取XProperty的定义信息
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="name">XProperty的Name</param>
        /// <returns></returns>
        public static XProperty.XPropertyDescription GetXPropertyDescription(object obj, string name)
        {
            Type type = obj.GetType();

            PropertyInfo[] propertyArr = type.GetProperties();

            for (int index = 0; index < propertyArr.Length; index++)
            {
                PropertyInfo propertyInfo = propertyArr[index];
                XPropertyAttribute xProperty = propertyInfo.GetCustomAttribute<XPropertyAttribute>(true);
                if (xProperty != null)
                {
                    if (name == xProperty.Name)
                    {
                        return new XProperty.XPropertyDescription(xProperty, propertyInfo);
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 设置对象XProperty的值
        /// </summary>
        /// <param name="context"></param>
        /// <param name="obj"></param>
        /// <param name="description"></param>
        /// <param name="value"></param>
        public static void SetXPropertyValue(XProperty.Converters.ConvertContext context,
            object obj, 
            XProperty.XPropertyDescription description, 
            CPPEI.Coolzon.Metadata.ValueNode value)
        {
            // 获取属性值转换器
            IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(description.PropertyInfo.PropertyType);
            if (converter != null)
            {
                object propertyValue = converter.Convert(context, value);
                if (propertyValue != null)
                {
                    description.PropertyInfo.SetValue(obj, propertyValue);
                }
            }
        }

        /// <summary>
        /// 获取对象XProperty的值
        /// </summary>
        /// <param name="context"></param>
        /// <param name="obj"></param>
        /// <param name="description"></param>
        /// <returns></returns>
        public static Coolzon.Metadata.ValueNode GetXPropertyValue(XProperty.Converters.ConvertContext context,
            object obj,
            XProperty.XPropertyDescription description)
        {
            // 获取属性值转换器
            IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(description.PropertyInfo.PropertyType);
            if (converter != null)
            {
                object propertyValue = description.PropertyInfo.GetValue(obj);
                return converter.ConvertBack(context, propertyValue);
            }
            return null;
        }

        /// <summary>
        /// 获取对象中所有的xproperty和PropertyInfo的对应关系
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Dictionary<XPropertyAttribute, PropertyInfo> GetXPropertyDictionary(object obj)
        {
            return null;
        }

        /// <summary>
        /// 获取对象中所有的xproperty
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<XPropertyAttribute> GetXProperties(object obj)
        {
            return null;
        }

        /// <summary>
        /// 保存对象的Xproperty的值
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<Metadata.Property> SaveXPropertyValue(object obj)
        {
            List<Metadata.Property> propertyMetadataList = new List<Metadata.Property>();

            Type type = obj.GetType();

            PropertyInfo[] propertyArr = type.GetProperties();

            for (int index = 0; index < propertyArr.Length; index++)
            {
                PropertyInfo propertyInfo = propertyArr[index];
                XPropertyAttribute xProperty = propertyInfo.GetCustomAttribute<XPropertyAttribute>(true);
                if (xProperty != null)
                {
                    IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(propertyInfo.PropertyType);

                    Metadata.Property propertyMetadta = new Metadata.Property();
                    propertyMetadta.Name = xProperty.Name;
                    propertyMetadta.ValueNode = converter.ConvertBack(null, propertyInfo.GetValue(obj));

                    propertyMetadataList.Add(propertyMetadta);
                }
            }
            return propertyMetadataList;
        }

        /// <summary>
        /// 加载xProperties的值
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="properties"></param>
        public static void LoadXPropertyValue(ConvertContext convertContext, object obj, List<Metadata.Property> properties)
        {
            if (properties == null || properties.Count == 0)
            {
                return;
            }

            Type type = obj.GetType();

            List<XPropertyDescription> descLst = XPropertyDescriptionCache.Instance.Get(type);

            for (int index = 0; index < descLst.Count; index++)
            {
                PropertyInfo propertyInfo = descLst[index].PropertyInfo;
                XPropertyAttribute xProperty =descLst[index].XPropertyAttribute;
                if (xProperty != null)
                {
                    if(xProperty.IsDeprecated)
                    {
                        Logger.WarningToTag(Library.LogXProperty, string.Format("属性:{0},{1}已被废弃，不设置给组件", xProperty.Name, xProperty.Caption));
                        continue;
                    }

                    for (int pIndex = 0; pIndex < properties.Count; pIndex++)
                    {
                        Metadata.Property propertyMetadata = properties[pIndex];
                        if (propertyMetadata.Name == xProperty.Name)
                        {
                            // 获取属性值转换器
                            IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(propertyInfo.PropertyType);
                            if (converter != null)
                            {
                                if (propertyMetadata.ValueNode == null)
                                {
                                    Metadata.ValueNode valueNode = new Metadata.ValueNode("Dynamic");
                                    valueNode.Attributes = new Dictionary<string, string>();
                                    valueNode.Attributes.Add("Value", propertyMetadata.ValueString);
                                    object propertyValue = converter.Convert(convertContext, valueNode);
                                    if (propertyValue != null)
                                    {
                                        propertyInfo.SetValue(obj, propertyValue);
                                    }
                                }
                                else
                                {
                                    object propertyValue = converter.Convert(convertContext, propertyMetadata.ValueNode);
                                    if (propertyValue != null)
                                    {
                                        propertyInfo.SetValue(obj, propertyValue);
                                    }
                                }
                            }
                            else
                            {
                                Logger.ErrorToTag(Library.LogXProperty, string.Format("属性:{0},{1}没有发现转换器", xProperty.Name, xProperty.Caption));
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 从元数据中转换出获取属性的值
        /// </summary>
        /// <param name="dp"></param>
        /// <param name="propertyMetadata"></param>
        /// <returns></returns>
        public static object ConvertPropertyValue(DependencyProperty dp, Metadata.Property propertyMetadata)
        {
            // 获取属性值转换器
            IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(dp.PropertyType);
            if (converter != null)
            {
                if (propertyMetadata.ValueNode == null)
                {
                    Metadata.ValueNode valueNode = new Metadata.ValueNode("Dynamic");
                    valueNode.Attributes = new Dictionary<string, string>();
                    valueNode.Attributes.Add("Value", propertyMetadata.ValueString);
                    return converter.Convert(null, valueNode);
                }
                else
                {
                    return converter.Convert(null, propertyMetadata.ValueNode);
                }
            }
            return null;
        }

        public static T ConvertPropertyValue<T>(Metadata.Property propertyMetadata)
        {
            // 获取属性值转换器
            IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(typeof(T));
            if (converter != null)
            {
                if (propertyMetadata.ValueNode == null)
                {
                    Metadata.ValueNode valueNode = new Metadata.ValueNode("Dynamic");
                    valueNode.Attributes = new Dictionary<string, string>();
                    valueNode.Attributes.Add("Value", propertyMetadata.ValueString);
                    return (T)converter.Convert(null, valueNode);
                }
                else
                {
                    return (T)converter.Convert(null, propertyMetadata.ValueNode);
                }
            }
            return default(T);
        }

        #region 某一类属性的处理
        /// <summary>
        /// 删除组件里的某一类属性,让这些属性可以被回收
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="part"></param>
        public static void UnloadXProperty<T1>(Part part)
        {
            Type t1Type = typeof(T1);
            Type type = part.GetType();

            PropertyInfo[] propertyArr = type.GetProperties();

            for (int index = 0; index < propertyArr.Length; index++)
            {
                PropertyInfo propertyInfo = propertyArr[index];
                XPropertyAttribute xProperty = propertyInfo.GetCustomAttribute<XPropertyAttribute>(true);
                if (xProperty != null && propertyInfo.PropertyType == t1Type)
                {
                    propertyInfo.SetValue(part, default(T1));
                }
            }
        }

        /// <summary>
        /// 为组件加载某一类属性
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="part"></param>
        public static void LoadXProperty<T1>(Part part)
        {
            Type t1Type = typeof(T1);
            List<Metadata.Property> properties = part.Metadata.Properties;
            if (properties == null || properties.Count == 0)
            {
                return;
            }

            Type type = part.GetType();

            PropertyInfo[] propertyArr = type.GetProperties();

            for (int index = 0; index < propertyArr.Length; index++)
            {
                PropertyInfo propertyInfo = propertyArr[index];
                XPropertyAttribute xProperty = propertyInfo.GetCustomAttribute<XPropertyAttribute>(true);
                if (xProperty != null && propertyInfo.PropertyType == t1Type)
                {
                    for (int pIndex = 0; pIndex < properties.Count; pIndex++)
                    {
                        Metadata.Property propertyMetadata = properties[pIndex];
                        if (propertyMetadata.Name == xProperty.Name)
                        {
                            // 获取属性值转换器
                            IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(propertyInfo.PropertyType);
                            if (converter != null)
                            {
                                if (propertyMetadata.ValueNode == null)
                                {
                                    Metadata.ValueNode valueNode = new Metadata.ValueNode("Dynamic");
                                    valueNode.Attributes = new Dictionary<string, string>();
                                    valueNode.Attributes.Add("Value", propertyMetadata.ValueString);
                                    object propertyValue = converter.Convert(null, valueNode);
                                    if (propertyValue != null)
                                    {
                                        propertyInfo.SetValue(part, propertyValue);
                                    }
                                }
                                else
                                {
                                    object propertyValue = converter.Convert(null, propertyMetadata.ValueNode);
                                    if (propertyValue != null)
                                    {
                                        propertyInfo.SetValue(part, propertyValue);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #region 属性的处理，排除部分属性
        /// <summary>
        /// 删除组件里的属性值，排除在外的属性不处理
        /// </summary>
        /// <param name="part"></param>
        /// <param name="exceptPropertyType">被排除的属性类型</param>
        public static void UnloadXProperties(UI.Part part, Type[] exceptPropertyType)
        {
            Type type = part.GetType();
            bool isExit = false;

            PropertyInfo[] propertyArr = type.GetProperties();

            for (int index = 0; index < propertyArr.Length; index++)
            {
                PropertyInfo propertyInfo = propertyArr[index];
                XPropertyAttribute xProperty = propertyInfo.GetCustomAttribute<XPropertyAttribute>(true);
                if (xProperty != null)
                {
                    isExit = false;
                    for (int iExcept = 0; iExcept < exceptPropertyType.Length; iExcept++)
                    {
                        if (exceptPropertyType[iExcept] == propertyInfo.PropertyType)
                        {
                            isExit = true;
                            break;
                        }
                    }

                    if (!isExit)
                    {
                        propertyInfo.SetValue(part, null);
                    }
                }
            }
        }

        /// <summary>
        /// 加载组件里的属性值，排除在外的属性不处理
        /// </summary>
        /// <param name="part"></param>
        /// <param name="exceptPropertyType">被排除的属性类型</param>
        public static void LoadXProperties(UI.Part part, Type[] exceptPropertyType)
        {
            bool isExit = false;
            List<Metadata.Property> properties = part.Metadata.Properties;
            if (properties == null || properties.Count == 0)
            {
                return;
            }

            Type type = part.GetType();

            PropertyInfo[] propertyArr = type.GetProperties();

            for (int index = 0; index < propertyArr.Length; index++)
            {
                PropertyInfo propertyInfo = propertyArr[index];
                XPropertyAttribute xProperty = propertyInfo.GetCustomAttribute<XPropertyAttribute>(true);
                if (xProperty != null)
                {
                    isExit = false;

                    for (int iExcept = 0; iExcept < exceptPropertyType.Length; iExcept++)
                    {
                        if (exceptPropertyType[iExcept] == propertyInfo.PropertyType)
                        {
                            isExit = true;
                            break;
                        }
                    }

                    if (isExit)
                    {
                        continue;
                    }

                    for (int pIndex = 0; pIndex < properties.Count; pIndex++)
                    {
                        Metadata.Property propertyMetadata = properties[pIndex];
                        if (propertyMetadata.Name == xProperty.Name)
                        {
                            // 获取属性值转换器
                            IPropertyValueConverter converter = PropertyValueConverterFactory.GetConverter(propertyInfo.PropertyType);
                            if (converter != null)
                            {
                                if (propertyMetadata.ValueNode == null)
                                {
                                    Metadata.ValueNode valueNode = new Metadata.ValueNode("Dynamic");
                                    valueNode.Attributes = new Dictionary<string, string>();
                                    valueNode.Attributes.Add("Value", propertyMetadata.ValueString);
                                    object propertyValue = converter.Convert(null, valueNode);
                                    if (propertyValue != null)
                                    {
                                        propertyInfo.SetValue(part, propertyValue);
                                    }
                                }
                                else
                                {
                                    object propertyValue = converter.Convert(null, propertyMetadata.ValueNode);
                                    if (propertyValue != null)
                                    {
                                        propertyInfo.SetValue(part, propertyValue);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        #endregion


        /// <summary>
        /// 删除组件里的属性值,如果属性是引用属性则设置为null，否则不处理
        /// </summary>
        /// <param name="part"></param>
        public static void ClearXProperties(UI.Part part)
        {
            int successCount = 0;
            int errorCount = 0;

            Type type = part.GetType();
            List<XPropertyDescription> descLst = XPropertyDescriptionCache.Instance.Get(type);

            for (int index = 0; index < descLst.Count; index++)
            {
                PropertyInfo propertyInfo = descLst[index].PropertyInfo;
                XPropertyAttribute xProperty = descLst[index].XPropertyAttribute;
                if (xProperty != null && !propertyInfo.PropertyType.IsValueType)
                {
                    try
                    {
                        propertyInfo.SetValue(part, null);
                        successCount++;
                    }
                    catch(Exception ex)
                    {
                        errorCount++;
                    }
                }
            }
            //Common.Logger.DebugToTag("Coolon.UI", "删除组件:{0}的属性，成功：{1}，失败：{2}", part.Name, successCount, errorCount);
        }
    }
}
